import path from 'path';

import { expect } from '@jest/globals';
import fse from 'fs-extra';

import { initExecuteCommand, runHvigorAsync, setDefaultStrictMode } from '../../common/common';
import { commonJson5Operation, decompressHapAndReadEntries } from '../../plugins/common-fun';
import {
  AbilityType,
  APIType,
  CaseLevel, CURRENT_HMOS_API,
  LanguageType,
  ModuleTemplateType,
  RuntimeOSType,
  SDKType,
} from '../../plugins/project-builder/models/constants';
import { Project } from '../../plugins/project-builder/models/project-models';
import { ICaseRecord } from '../../plugins/report-builder/report-models';
import { TestCaseBuilder } from '../../plugins/task-builder/task-case-builder';
import { ProjectBuildOption, TestCaseFun } from '../../plugins/task-builder/test-case';
import { TestTaskOption, TestTaskOptionBuilder } from '../../plugins/task-builder/test-task-option';
import {getJson5Obj} from '../../../../src/utils/json-util';

const projectBuilderOption: ProjectBuildOption = {
  template: {
    sdk: SDKType.Single,
    runtimeOS: RuntimeOSType.HarmonyOS,
    apiVersion: CURRENT_HMOS_API,
    apiType: APIType.STAGE,
    language: LanguageType.ArkTs,
    abilityType: AbilityType.Application,
    entryTemplateType: ModuleTemplateType.EmptyAbility,
  },
};
/**
 *  1. ets目录下增加资源文件，配置资源过滤规则
 *  2. 构建hap
 *  3. 构建之后检查产物资源是否被过滤
 *  4. 更改配置项看增量是否生效
 */
const testFun: TestCaseFun = async (project: Project, taskConfig: TestTaskOption, record: ICaseRecord) => {
  const projectRoot = project.projectRootPath();
  setDefaultStrictMode(projectRoot);

  const entryPath = project.getModule('entry').moduleRootPath();

  const mainSrcPath = path.resolve(entryPath, 'src', 'main', 'ets', 'components','mainpage');

  // 创建png, owner, yaml文件, 测试不同目录层级
  const pngPath = path.resolve(mainSrcPath, 'aaa.png');
  const ownerPath = path.resolve(mainSrcPath, 'owner');
  const yamlPath = path.resolve(mainSrcPath, 'subDir','bbb.yaml');
  const createSet = [pngPath, ownerPath, yamlPath];

  createSet.forEach(filePath => {
    fse.ensureFileSync(filePath);
    fse.writeFileSync(filePath, '');
  });

  await commonJson5Operation(path.resolve(entryPath, 'build-profile.json5'), async (json5) => {
    json5.buildOption =
      {
        resOptions: {
          copyCodeResource: {
            enable: true,
            excludes: ['**/owner', '**/*.yaml']
          }
        }
      };
  });

  // 构建hap包
  const assembleHapCmd = ['assembleHap'];
  const assembleHapResult = await runHvigorAsync(projectRoot, assembleHapCmd);
  record.addStep('编译构建Hap', assembleHapResult);
  expect(assembleHapResult.stdout).toContain('BUILD SUCCESSFUL');


  // 检查产物目录中ets目录下资源是否被过滤
  const outPutPath = path.resolve(entryPath, 'build', 'default', 'outputs', 'default');
  const hapName = (await fse.readdir(outPutPath)).filter((item) => item.endsWith('.hap'))[0];
  const hapPath = path.resolve(outPutPath, hapName);
  expect(fse.existsSync(hapPath)).toEqual(true);

  const hapFiles = await decompressHapAndReadEntries(hapPath);
  const fileNames = hapFiles.map((item) => item[0]);
  const hasPng = fileNames.some((fileName) => fileName.endsWith('.png'));
  const hasYaml = fileNames.some((fileName) => fileName.endsWith('.yaml'));
  const hasOwner = fileNames.some((fileName) => fileName.endsWith('owner'));
  expect(hasPng).toEqual(true);
  expect(hasYaml).toEqual(false);
  expect(hasOwner).toEqual(false);


  // 修改配置项excludes，触发增量判断
  await commonJson5Operation(path.resolve(entryPath, 'build-profile.json5'), async (json5) => {
    json5.buildOption =
      {
        resOptions: {
          copyCodeResource: {
            enable: true,
            excludes: ['**/owner']
          }
        }
      };
  });

  const assembleHapResult2 = await runHvigorAsync(projectRoot, assembleHapCmd);
  record.addStep('增量编译构建Hap', assembleHapResult2);
  expect(assembleHapResult2.stdout).toContain('Finished :entry:default@CompileArkTS');

  // 产物中存在Yaml文件
  const hapFiles2 = await decompressHapAndReadEntries(hapPath);
  const fileNames2 = hapFiles2.map((item) => item[0]);
  const hasYaml2 = fileNames2.some((fileNames) => fileNames.endsWith('.yaml'));
  expect(hasYaml2).toEqual(true);
  

  // 修改配置项enable，触发增量判断
  await commonJson5Operation(path.resolve(entryPath, 'build-profile.json5'), async (json5) => {
    json5.buildOption =
      {
        resOptions: {
          copyCodeResource: {
            enable: false,
            excludes: ['**/owner']
          }
        }
      };
  });

  const assembleHapResult3 = await runHvigorAsync(projectRoot, assembleHapCmd);
  record.addStep('增量编译构建Hap', assembleHapResult3);
  expect(assembleHapResult3.stdout).toContain('Finished :entry:default@CompileArkTS');

  // 在false下，修改excludes，不触发增量
  await commonJson5Operation(path.resolve(entryPath, 'build-profile.json5'), async (json5) => {
    json5.buildOption =
      {
        resOptions: {
          copyCodeResource: {
            enable: false,
            excludes: []
          }
        }
      };
  });

  const assembleHapResult4 = await runHvigorAsync(projectRoot, assembleHapCmd);
  record.addStep('增量编译构建Hap', assembleHapResult4);
  expect(assembleHapResult4.stdout).toContain('UP-TO-DATE :entry:default@CompileArkTS');


};

TestCaseBuilder.builder()
  .caseName('copy_resource_in_src_main')
  .description('控制src/main中的资源文件复制')
  .projectBuilderOption(projectBuilderOption)
  .taskConfig(TestTaskOptionBuilder.builder().caseLevel(CaseLevel.AR).build())
  .testFun(testFun)
  .load();
